# -*- coding: utf-8 -*-
"""
@author:xuyuntao
@time:2021/5/4:15:36
@email:xuyuntao@189.cn
"""
"""第四章末尾研究阵列天线接收多个信号进行空域滤波时，信源数的影响
可以通过runfile或os.system外部传入控制参数：
avgTimes：计算一个特征量使用的信号个数，越多，其平均值约准确
runTimes：计算识别率的分母，即一个特征量的计算遍数，越大，跳变越小
SNRStart：信噪比轴的左边界
SNREnd：信噪比轴的右边界
SNRRes：信噪比轴分辨率
doaSignalsList：信号源数列表，可传入如'[2,3]'这样用字符串表示的列表，
                注意，列表中整数必须大于等于2，1个信源为默认研究情况"""
import numpy
import os
import time
import csv
import datetime
import threading
from Tools import drawLine,drawColorMap,MT
from recognize import getRecoRatio,quickModArr,getRecoRatio_s,getRecoRatio_s_doa
from Tools import get_desktop
import argparse
parser = argparse.ArgumentParser(description='控制性参数')
parser.add_argument('--avgTimes', type=int, default = 40)
parser.add_argument('--runTimes', type=int, default=250)
parser.add_argument('--SNRStart', type=float, default=-8.0)
parser.add_argument('--SNREnd', type=float, default=10.0)
parser.add_argument('--SNRRes', type=float, default=1.0)
parser.add_argument('--doaSignalsList', type=str, default="[2,3]")
args = parser.parse_args()
print(args)

lock = threading.RLock()

def getRecognizeRatioThread(constelArr, signalArr, timeSeriesArr, modType, step, snr,
                            runTimes, SNR_I, antArr:bool=False, carrierFreq:int=1000, seperate:int=100,
                            doaSignals:int=3, antPairN=8, antDis=0.5, a_t=1.0,
                            noiseRad:float=0.1 * numpy.pi):
    """获取指定调制方式指定信噪比下的调制识别率，多信源版"""
    global ratio_snr_mt_line   # 读取全局变量，方便同步修改
    if antArr:
        print("-------------阵列天线-------------")
    else:
        print("-------------普通天线-------------")
    recognizeRatio=getRecoRatio_s_doa(
        constelArr,signalArr,timeSeriesArr,modType,step,snr,
        runTimes,antArr,carrierFreq,seperate,doaSignals,
        antPairN,antDis,a_t,noiseRad)
    lock.acquire()
    ratio_snr_mt_line[SNR_I]=recognizeRatio
    lock.release()
    return recognizeRatio

def getRecognizeRatioThread_2(constelArr, signalArr, timeSeriesArr, modType, step, snr,
                            runTimes, SNR_I, antArr:bool=False, carrierFreq:int=1000, seperate:int=100,
                            signalWay=30.0, antPairN=8, antDis=0.5, a_t=1.0,
                            noiseRad:float=0.1 * numpy.pi):
    """获取指定调制方式指定信噪比下的调制识别率，单信源版"""
    global ratio_snr_mt_line   # 读取全局变量，方便同步修改
    if antArr:
        print("-------------阵列天线-------------")
    else:
        print("-------------普通天线-------------")
    recognizeRatio=getRecoRatio_s(
        constelArr,signalArr,timeSeriesArr,modType,step,snr,
        runTimes,antArr,carrierFreq,seperate,signalWay,
        antPairN,antDis,a_t,noiseRad)
    lock.acquire()
    ratio_snr_mt_line[SNR_I]=recognizeRatio
    lock.release()
    return recognizeRatio


startTime=time.time()
avgTimes = args.avgTimes  # 计算特征值时进行平均的次数
runTimes=args.runTimes  # 用作计算识别百分率的分母
choseTypes=[
    MT("qam",256),
    ]
SNRList=list(numpy.arange(args.SNRStart,args.SNREnd,args.SNRRes))  # 信噪比轴  [-1,0,1,2,3,...]
bytesRate=100
carrierFreq=1000
sampleFreq=6000
seperate=100
doaSignalsList=eval(args.doaSignalsList) # 空域滤波信源数
print("doaSignalsList",doaSignalsList)
a_t = 1.0
bytesLen=300
fullTimes=len(choseTypes)*len(SNRList)*(len(doaSignalsList)+1)
nowTime=0
firstTime=True
savePath=os.path.join(get_desktop(),"Paper_Pictures\\",
                      "chapter_4_simulation_ratio_snr_mt_AntArr_doa")

for mt_I in range(len(choseTypes)):
    ratio_snr_mt_line=numpy.zeros(len(SNRList),dtype=numpy.float64)
    mt=choseTypes[mt_I]
    constelArr,signalArr,timeSeriesArr= \
        quickModArr(mt.type, mt.step, avgTimes, bytesLen,
                    bytesRate, carrierFreq,sampleFreq, seperate)
    threadList=[]
    for SNR_I in range(len(SNRList)):
        SNR=SNRList[SNR_I]
        threadList.append(threading.Thread(target=getRecognizeRatioThread_2,
                                           args=[constelArr,signalArr,timeSeriesArr,
                                                 mt.type,mt.step, SNR, runTimes,
                                                 SNR_I, True,carrierFreq,seperate,
                                                 30.0,8,0.5, a_t]))
        threadList[-1].setDaemon(True)
        threadList[-1].start()
    for threadFunc in threadList:
        threadFunc.join()
        nowTime+=1
        print("{2}{3}现在第{0}次，总共{1}次。".format(nowTime,fullTimes,
                                             choseTypes[mt_I].step,
                                             choseTypes[mt_I].type))
    del threadList,threadFunc,mt,SNR,constelArr,signalArr,timeSeriesArr
    if firstTime:
        with open(savePath+".csv","w",newline="") as f:
            csvWri=csv.writer(f)
            csvWri.writerow(ratio_snr_mt_line)
            del csvWri
        firstTime=False
    else:
        with open(savePath+".csv","a+",newline="") as f:
            csvWri=csv.writer(f)
            csvWri.writerow(ratio_snr_mt_line)
            del csvWri
    del ratio_snr_mt_line

for doaSignals in doaSignalsList:
    for mt_I in range(len(choseTypes)):
        ratio_snr_mt_line=numpy.zeros(len(SNRList),dtype=numpy.float64)
        mt=choseTypes[mt_I]
        constelArr,signalArr,timeSeriesArr= \
            quickModArr(mt.type, mt.step, avgTimes, bytesLen,
                        bytesRate, carrierFreq,sampleFreq, seperate)
        threadList=[]
        for SNR_I in range(len(SNRList)):
            SNR=SNRList[SNR_I]
            threadList.append(threading.Thread(target=getRecognizeRatioThread,
                                               args=[constelArr,signalArr,timeSeriesArr,
                                                     mt.type,mt.step, SNR, runTimes,
                                                     SNR_I, True,carrierFreq,seperate,
                                                     doaSignals,8,0.5, a_t]))
            threadList[-1].setDaemon(True)
            threadList[-1].start()
        for threadFunc in threadList:
            threadFunc.join()
            nowTime+=1
            print("{2}{3}现在第{0}次，总共{1}次。".format(nowTime,fullTimes,
                                                 choseTypes[mt_I].step,
                                                 choseTypes[mt_I].type))
        del threadList,threadFunc,mt,SNR,constelArr,signalArr,timeSeriesArr
        if firstTime:
            with open(savePath+".csv","w",newline="") as f:
                csvWri=csv.writer(f)
                csvWri.writerow(ratio_snr_mt_line)
                del csvWri
            firstTime=False
        else:
            with open(savePath+".csv","a+",newline="") as f:
                csvWri=csv.writer(f)
                csvWri.writerow(ratio_snr_mt_line)
                del csvWri
        del ratio_snr_mt_line

with open(savePath+".csv","r") as f:
    csvRea=csv.reader(f)
    ratio_mt_snr=[]
    for _ in csvRea:
        ratio_mt_snr.append([__.strip() for __ in _])
    ratio_snr_mt=numpy.array(ratio_mt_snr,dtype=numpy.float64)
    del ratio_mt_snr,csvRea

SNRList_arr=numpy.array(SNRList).reshape([1,-1]).repeat(len(choseTypes*(len(doaSignalsList)+1)),axis=0)
legend=[str(_.step)+_.type.upper()+"_SignalN=1" for _ in choseTypes]
for doaSignals in doaSignalsList:
    legend+=[str(_.step)+_.type.upper()+"_SignalN="+str(doaSignals) for _ in choseTypes]
fig=drawLine(1,SNRList_arr,ratio_snr_mt,"信噪比（dB）","识别率",legend,marker=True)
fig.savefig(savePath+".svg", dpi=300, format="svg",bbox_inches='tight',
            pad_inches=0.0,transparent=True)
fig.show()
endTime=time.time()
print("计算识别率共耗时：",str(datetime.timedelta(seconds=abs(endTime-startTime))))